/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "MPIRASTROFileReader.h"

@implementation MPIRASTROFileReader

- (void) addDoubleValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_double; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"double-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%f", evrastro->v_double[i]]];
		[ide release];
	}
}

- (void) addFloatValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_float; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"float-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%f", evrastro->v_float[i]]];
		[ide release];
	}
}

- (void) addUInt64ValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_uint64; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"uint64-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%l", evrastro->v_uint64[i]]];
		[ide release];
	}
}

- (void) addUInt32ValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_uint32; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"uint32-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%d", evrastro->v_uint32[i]]];
		[ide release];
	}
}

- (void) addUInt16ValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_uint16; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"uint16-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%d", evrastro->v_uint16[i]]];
		[ide release];
	}
}

- (void) addUInt8ValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_uint8; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"uint8-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%d", evrastro->v_uint8[i]]];
		[ide release];
	}
}

- (void) addStringValuesOf: (rst_event_t *) evrastro toGFields: (GFields *) f
{
	int i;
	for (i = 0; i < evrastro->ct.n_string; i++) {
		GIdentifier *ide = [[GIdentifier alloc] init];
		[ide addValue: [NSString stringWithFormat: @"string-%d", i]];
		[f setFieldWithKey: ide withValue: [NSString stringWithFormat: @"%s", evrastro->v_string[i]]];
		[ide release];
	}
}

- (GEvent *) getGEventWithEvent: (rst_event_t *) evrastro withProvider: (id) provider
{
	GEvent *ev = [[GEvent alloc] init];
	GFields *fields = [[GFields alloc] init];

	/* setting timestamp */
	GTimestamp *timestamp = [[GTimestamp alloc] init];
	[timestamp setTimestamp: [NSString stringWithFormat: @"%lld",evrastro->timestamp]];
	[ev setTimestamp: timestamp];	
	[timestamp release];

	/* setting identifier */
	GIdentifier *identifier = [[GIdentifier alloc] init];
	[identifier addValue: [NSString stringWithFormat: @"%d", evrastro->type]];
	[ev setIdentifier: identifier];
	[identifier release];

	/* setting static fields - machine */
	GIdentifier *id1 = [[GIdentifier alloc] init];
	[id1 addValue: [NSString stringWithFormat: @"%@", @"machine"]];
	[fields setFieldWithKey: id1 withValue: [provider machineForNode: evrastro->id1]];
	[id1 release];

	/* setting static fields - thread */
	GIdentifier *id2 = [[GIdentifier alloc] init];
	[id2 addValue: [NSString stringWithFormat: @"%@", @"thread"]];
	[fields setFieldWithKey: id2 withValue: [NSString stringWithFormat: @"%d", evrastro->id2]];
	[id2 release];

	/* setting static fields - node */
	GIdentifier *id3 = [[GIdentifier alloc] init];
	[id3 addValue: [NSString stringWithFormat: @"%@", @"node"]];
	[fields setFieldWithKey: id3 withValue: [NSString stringWithFormat: @"%d", evrastro->id1]];
	[id3 release];

	/* setting dynamic fields */
	[self addDoubleValuesOf: evrastro toGFields: fields];
	[self addFloatValuesOf: evrastro toGFields: fields];
	[self addUInt64ValuesOf: evrastro toGFields: fields];
	[self addUInt32ValuesOf: evrastro toGFields: fields];
	[self addUInt16ValuesOf: evrastro toGFields: fields];
	[self addUInt8ValuesOf: evrastro toGFields: fields];
	[self addStringValuesOf: evrastro toGFields: fields];

	/* settind fields to the event */
	[ev setFields: fields];
	[fields release];

	[ev autorelease];
	return ev;
}

/* next method is used by MPIRASTROEvent invocation */
- (NSString *) machineForNode: (int) node
{
	if ([hostnames count] == 0){
		return nil;
	}else{
		return [hostnames objectForKey:[NSString stringWithFormat:@"%d",node]];
	}
}

- (GTimestamp *) time 
{
	return [topEvent timestamp];
}

- (void) dealloc
{
	[filenames release];
	[topEvent release];
	[hostnames release];
	[super dealloc];
}


- (id) initWithFileName: (NSString *) traceFile
	andSyncFileName: (NSString *) syncFile
{
	return nil;
}

- (id) initWithMultipleFiles: (NSArray *) traceFiles
	andSyncFileName: (NSString *) syncFile
{
	int i;

	self = [super init];
	hostnames = [[NSMutableDictionary alloc] init];

	
	if (traceFiles == nil){
		NSLog (@"MPIRASTROFileReader: filenames should be provided");
		return nil;
	}
	if (syncFile == nil){
		syncFile = [NSString stringWithFormat: @"nofile"];
	}
	filenames = traceFiles;
	[filenames retain];

	// opening many libRastro trace files 
	for (i = 0; i < [filenames count]; i++){
		char *file = (char *)[[filenames objectAtIndex: i] cString];
		char *sync = (char *)[syncFile cString];
		if (rst_open_file (file, &data, sync, 100000) == -1){
			NSLog (@"MPIRASTROFileReader: error opening '%@'",
					[filenames objectAtIndex: i]);
			[filenames release];
			[hostnames release];
			return nil;
		}
	}

	// decoding first event 
	if (rst_decode_event (&data, &event) == RST_NOK){
		[hostnames release];
		[filenames release];
		return nil;
	}else{
		int i;
		for (i = 0; i < data.quantity; i++){
			rst_one_file_t *x;
			x = data.of_data[i];
			if (x->id1 == event.id1 && x->id2 == event.id2){
				[hostnames setObject: [NSString stringWithCString: x->hostname]	forKey:	[NSString stringWithFormat: @"%d", x->id1]];
			}
		}
	}

	// first event decoded in a GenericEvent 
	topEvent = [self getGEventWithEvent: &event withProvider:self];
	[topEvent retain];

	return self;
}


/*
 * This method is called by the Integrator
 */
- (GEvent *) event
{
	GEvent *ret;

	// if topEvent is nil, this means there are no more events
	if (topEvent == nil){
		return nil;
	}

	// saving topEvent in order to return it
	ret = topEvent;
	topEvent = nil;

	// decoding next topEvent
	if (rst_decode_event (&data, &event) == RST_NOK){
		topEvent = nil;
		[ret autorelease];
		return ret;
	}else{
		int i;
		for (i = 0; i < data.quantity; i++){
			rst_one_file_t *x;
			x = data.of_data[i];
			if (x->id1 == event.id1 && x->id2 == event.id2){
				[hostnames setObject: [NSString stringWithCString: x->hostname]	forKey:	[NSString stringWithFormat: @"%d", x->id1]];
			}
		}
	}

	// new topEvent as GenericEvent
	topEvent = [self getGEventWithEvent: &event withProvider:self];
	[topEvent retain];

	// preparing ret for returning it
	[ret autorelease];
	return ret;
}
@end
